/*
 * Cpdma.c
 *
 *  Created on: Oct 13, 2018
 *      Author: ax
 */

#include <Hw/Cpdma.h>
#include <Hw/Qmss.h>

#include <ti/csl/cslr_device.h>
#include <ti/csl/cslr_cppidma_global_config.h>
#include <ti/csl/cslr_cppidma_rx_flow_config.h>
#include <ti/csl/cslr_cppidma_rx_channel_config.h>
#include <ti/csl/cslr_cppidma_tx_channel_config.h>
#include <ti/csl/cslr_cppidma_tx_scheduler_config.h>


void
Cpdma_rxChannelEnable(
    CpDma   dma,
    Uint16  channel
){
    CSL_Cppidma_rx_channel_configRegs* const hCpdma[CpDma_CNT] = {
        (CSL_Cppidma_rx_channel_configRegs*) CSL_QM_SS_CFG_CPPI_DMA_RX_CFG_REGS,
        (CSL_Cppidma_rx_channel_configRegs*) CSL_SRIO_CONFIG_CPPI_DMA_RX_CFG_REGS,
        (CSL_Cppidma_rx_channel_configRegs*) CSL_PA_SS_CFG_CPPI_DMA_RX_CFG_REGS };

    hCpdma[dma]->RX_CHANNEL_GLOBAL_CONFIG[channel].RX_CHANNEL_GLOBAL_CONFIG_REG |=
            CSL_CPPIDMA_RX_CHANNEL_CONFIG_RX_CHANNEL_GLOBAL_CONFIG_REG_RX_ENABLE_MASK;
}

void
Cpdma_txChannelEnable(
    CpDma   dma,
    Uint16  channel
){
    CSL_Cppidma_tx_channel_configRegs* const hCpdma[CpDma_CNT] = {
        (CSL_Cppidma_tx_channel_configRegs*) CSL_QM_SS_CFG_CPPI_DMA_TX_CFG_REGS,
        (CSL_Cppidma_tx_channel_configRegs*) CSL_SRIO_CONFIG_CPPI_DMA_TX_CFG_REGS,
        (CSL_Cppidma_tx_channel_configRegs*) CSL_PA_SS_CFG_CPPI_DMA_TX_CFG_REGS };

    hCpdma[dma]->TX_CHANNEL_GLOBAL_CONFIG[channel].TX_CHANNEL_GLOBAL_CONFIG_REG_A |=
            CSL_CPPIDMA_TX_CHANNEL_CONFIG_TX_CHANNEL_GLOBAL_CONFIG_REG_A_TX_ENABLE_MASK;
}

void
Cpdma_globalEnable(
    CpDma   dma,
    Uint16  rxPriority,
    Uint16  txPriority,
    bool    loopback
){
    CSL_Cppidma_global_configRegs* const hCpdma[CpDma_CNT] = {
        (CSL_Cppidma_global_configRegs*) CSL_QM_SS_CFG_CPPI_DMA_GLOBAL_CFG_REGS,
        (CSL_Cppidma_global_configRegs*) CSL_SRIO_CONFIG_CPPI_DMA_GLOBAL_CFG_REGS,
        (CSL_Cppidma_global_configRegs*) CSL_PA_SS_CFG_CPPI_DMA_GLOBAL_CFG_REGS };

    CSL_Cppidma_global_configRegs* const cpdma = hCpdma[dma];

    RegVal reg = cpdma->PRIORITY_CONTROL_REG;
    CSL_FINS(reg, CPPIDMA_GLOBAL_CONFIG_PRIORITY_CONTROL_REG_RX_PRIORITY, rxPriority);
    CSL_FINS(reg, CPPIDMA_GLOBAL_CONFIG_PRIORITY_CONTROL_REG_TX_PRIORITY, txPriority);
    cpdma->PRIORITY_CONTROL_REG = reg;

    cpdma->QM_BASE_ADDRESS_REG[0] = 0x34020000;     /*queue 0~4095*/
    cpdma->QM_BASE_ADDRESS_REG[1] = 0x34030000;     /*queue 4096~8191*/

    if (loopback)
        reg = CSL_FMK(CPPIDMA_GLOBAL_CONFIG_EMULATION_CONTROL_REG_LOOPBACK_EN, 1u)
            | CSL_FMK(CPPIDMA_GLOBAL_CONFIG_EMULATION_CONTROL_REG_SOFT, 0)
            | CSL_FMK(CPPIDMA_GLOBAL_CONFIG_EMULATION_CONTROL_REG_FREE, 0);
    else
        reg = CSL_FMK(CPPIDMA_GLOBAL_CONFIG_EMULATION_CONTROL_REG_LOOPBACK_EN, 0)
            | CSL_FMK(CPPIDMA_GLOBAL_CONFIG_EMULATION_CONTROL_REG_SOFT, 0)
            | CSL_FMK(CPPIDMA_GLOBAL_CONFIG_EMULATION_CONTROL_REG_FREE, 0);
    cpdma->EMULATION_CONTROL_REG = reg;
}

void
Cpdma_rxFlowConfig(
    CpDma       dma,
    RxFlowCfg   cfg,
    Uint16      idx
){
    Uint32 reg = 0;

    CSL_Cppidma_rx_flow_configRegs* const Cpdma[CpDma_CNT] = {
       (CSL_Cppidma_rx_flow_configRegs*) CSL_QM_SS_CFG_CPPI_DMA_RX_FLOW_CFG_REGS,
       (CSL_Cppidma_rx_flow_configRegs*) CSL_SRIO_CONFIG_CPPI_DMA_RX_FLOW_CFG_REGS,
       (CSL_Cppidma_rx_flow_configRegs*) CSL_PA_SS_CFG_CPPI_DMA_RX_FLOW_CFG_REGS };

    CSL_Cppidma_rx_flow_configRx_flow_configRegs* const flow
        = &Cpdma[dma]->RX_FLOW_CONFIG[idx];

    /* Rx flow configuration register A */
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_A_RX_DEST_QNUM, cfg->dest_qnum);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_A_RX_DEST_QMGR, QMGR(cfg->dest_qnum));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_A_RX_SOP_OFFSET, cfg->sop_offset);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_A_RX_PS_LOCATION, cfg->ps_location);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_A_RX_DESC_TYPE, cfg->desc_type);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_A_RX_ERROR_HANDLING, cfg->error_handling);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_A_RX_PSINFO_PRESENT, cfg->psinfo_present);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_A_RX_EINFO_PRESENT, cfg->einfo_present);
    flow->RX_FLOW_CONFIG_REG_A = reg;

    reg = 0;
    /* Rx flow configuration register B */
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_B_RX_DEST_TAG_LO, cfg->dest_tag_lo);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_B_RX_DEST_TAG_HI, cfg->dest_tag_hi);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_B_RX_SRC_TAG_LO, cfg->src_tag_lo);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_B_RX_SRC_TAG_HI, cfg->src_tag_hi);
    flow->RX_FLOW_CONFIG_REG_B = reg;

    reg = 0;
    /* Rx flow configuration register C */
    Uint32 temp = ((cfg->size_thresh0_en) | (cfg->size_thresh1_en << 1) | (cfg->size_thresh2_en << 2));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_C_RX_SIZE_THRESH_EN, temp);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_C_RX_DEST_TAG_LO_SEL, cfg->dest_tag_lo_sel);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_C_RX_DEST_TAG_HI_SEL, cfg->dest_tag_hi_sel);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_C_RX_SRC_TAG_LO_SEL, cfg->src_tag_lo_sel);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_C_RX_SRC_TAG_HI_SEL, cfg->src_tag_hi_sel);
    flow->RX_FLOW_CONFIG_REG_C = reg;

    reg = 0;
    /* Rx flow configuration register D */
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_D_RX_FDQ1_QNUM, QNUM(cfg->fdq1_qnum));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_D_RX_FDQ1_QMGR, QMGR(cfg->fdq1_qnum));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_D_RX_FDQ0_SZ0_QNUM, QNUM(cfg->fdq0_sz0_qnum));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_D_RX_FDQ0_SZ0_QMGR, QMGR(cfg->fdq0_sz0_qnum));
    flow->RX_FLOW_CONFIG_REG_D = reg;

    reg = 0;
    /* Rx flow configuration register E */
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_E_RX_FDQ3_QNUM, QNUM(cfg->fdq3_qnum));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_E_RX_FDQ3_QMGR, QMGR(cfg->fdq3_qnum));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_E_RX_FDQ2_QNUM, QNUM(cfg->fdq2_qnum));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_E_RX_FDQ2_QMGR, QMGR(cfg->fdq2_qnum));
    flow->RX_FLOW_CONFIG_REG_E = reg;

    reg = 0;
    /* Rx flow configuration register F */
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_F_RX_SIZE_THRESH1, (cfg->size_thresh1 >> 5));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_F_RX_SIZE_THRESH0, (cfg->size_thresh0  >> 5));
    flow->RX_FLOW_CONFIG_REG_F = reg;

    reg = 0;
    /* Rx flow configuration register G */
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_G_RX_FDQ0_SZ1_QNUM, QNUM(cfg->fdq0_sz1_qnum));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_G_RX_FDQ0_SZ1_QMGR, QMGR(cfg->fdq0_sz1_qnum));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_G_RX_SIZE_THRESH2, (cfg->size_thresh2) >> 5);
    flow->RX_FLOW_CONFIG_REG_G = reg;

    reg = 0;
    /* Rx flow configuration register H */
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_H_RX_FDQ0_SZ3_QNUM, cfg->fdq0_sz3_qnum);
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_H_RX_FDQ0_SZ3_QMGR, QMGR(cfg->fdq0_sz3_qnum));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_H_RX_FDQ0_SZ2_QNUM, QNUM(cfg->fdq0_sz2_qnum));
    CSL_FINS(reg, CPPIDMA_RX_FLOW_CONFIG_RX_FLOW_CONFIG_REG_H_RX_FDQ0_SZ2_QMGR, QMGR(cfg->fdq0_sz2_qnum));
    flow->RX_FLOW_CONFIG_REG_H = reg;
}
